<?php
/**
 * Simple User object adapting Standard Authority objects for ID and Permissions
 * Passing an instance of this class without Athorities is the equivelent of passing guest
 * 
 * @author Alton Crossley <crossleyframework@nogahidebootstrap.com>
 * @package Crossley Framework
 *  
 * @copyright Copyright (c) 2003-2009, Nogaide BootStrap INC. All rights reserved.
 * @license BSD http://opensource.org/licenses/bsd-license.php
 * @version $Id:$
 * 
 */
class X_User implements X_User_Interface
{
    /**
     * User Detail Data
     * @var unknown_type
     */
    protected $_aUserData = array();
    /**
     * unique identifier
     * @var string
     */
    protected $_sUid;
    /**
     * Instance of Id Authority
     * @var X_User_Id_Authority_Interface
     */
    protected $_oId;
    /**
     * Singelton Instance of Id Authority
     * @var X_User_Id_Authority_Interface
     */
    static protected $_oRegisteredIdAuthority;
    /**
     * Instance of Permission Authority
     * if no Authority is given to this instance the static is used
     * @var X_User_Permission_Authority_Interface
     */
    protected $_oPermission;
    /**
     * Singelton Instance of Permission Authority
     * if no Authority is given to this instance the static is used
     * @var X_User_Permission_Authority_Interface
     */
    static protected $_oRegisteredPermissionAuthority;
   
	function __construct()
	{
		if ($this->_checkIdAuthority())
		{
			self::$_oRegisteredIdAuthority->setIdentity($this);
		}
		
	}
	/**
     * @see X_User_Interface
     * @return bool
     */
	public function confirm()
    {
        if (!$this->_checkIdAuthority()) return false;

        return $this->_oId->verifyUser($this);

    }
    /**
     * check the Permission Authority and assign it from the Static
     * if available
     * @return boolean
     */
    protected function _checkPermissionAuthority()
    {
        if (empty($this->_oPermission) && empty(self::$_oRegisteredPermissionAuthority))
        {
            return false;
        }
        else if(empty($this->_oPermission))
        {
            $this->_oPermission = self::$_oRegisteredPermissionAuthority;
        }
        
        return true;
    }
    
	/**
     * @param X_User_Permission_Authority_Interface $_oPermission the $_oPermission to set
     */
    public function setPermissionAuthority(X_User_Permission_Authority_Interface $oPermission)
    {
        $this->_oPermission = $oPermission;
    }
    /**
     * register a static Permission Authority
     * @param X_User_Permission_Authority_Interface $oPermission
     * @return void
     */
    static public function registerPermissionAuthority(X_User_Permission_Authority_Interface $oPermission)
    {
        self::$_oRegisteredPermissionAuthority = $oPermission;
    }
    /**
     * get the registered Permission Authority
     * @return X_User_Permission_Authority_Interface
     */
    static public function getRegisteredPermissionAuthority()
    {
        return self::$_oRegisteredPermissionAuthority;
    }
	/**
     * @return the $_oPermission
     */
    public function getPermissionAuthority()
    {
        $this->_checkPermissionAuthority();
        return $this->_oPermission;
    }
	/**
     * check the Id Authority and assign it from the Static
     * if available
     * @return boolean
     */
    protected function _checkIdAuthority()
    {
        if (empty($this->_oId) && empty(self::$_oRegisteredIdAuthority))
        {
            // no athority set (no big deal)
            return false;
        }
        else if(empty($this->_oId))
        {
            $this->_oId = self::$_oRegisteredIdAuthority;
        }
        
        if (!($this->_oId instanceof X_User_Id_Authority_Interface))
        {
        	trigger_error("id authority is not an instance of X_User_Id_Authority_Interface", E_USER_WARNING);
        }
        
        return true;
    }
	/**
     * @param X_User_Id_Authority_Interface $_oId the $_oId to set
     */
    public function setIdAuthority(X_User_Id_Authority_Interface $oId)
    {
        $this->_oId = $oId;
    }
    /**
     * register a static Id Athority
     * @param X_User_Id_Athority_Interface $oId
     * @return void
     */
    static public function registerIdAuthority(X_User_Id_Authority_Interface $oId)
    {
        self::$_oRegisteredIdAuthority = $oId;
    }
    /**
     * get the registered static Id Authority
     * @return X_User_Id_Authority_Interface
     */
    static public function getRegisteredIdAuthority()
    {
        $this->_checkIdAuthority();
        return self::$_oRegisteredIdAuthority;
    }
	/**
     * @return the $_oId
     */
    public function getIdAuthority()
    {
        $this->_checkIdAuthority();
        return $this->_oId;
    }

	/**
	 * @see X_User_Interface
     * @param $aData
     */
    public function setData(array $aData)
    {    	
        $this->_aUserData = $aData;
        if (array_key_exists('email', $aData))
        {
        	$this->setEmail($aData['email']);
        }
    	if (array_key_exists('name', $aData))
        {
        	$this->setName($aData['name']);
        }
    	if (array_key_exists('printable_name', $aData))
        {
        	$this->setPrintableName($aData['printable_name']);
        }
    	if (array_key_exists('uid', $aData))
        {
        	$this->setUid($aData['uid']);
        }
        return $this;
    }
    
	/**
     * @see X_User_Interface
     * @return array
     */
    public function getData($sKey = null)
    {
        if ($sKey && array_key_exists($sKey, $this->_aUserData))
        {
            return $this->_aUserData[$sKey];
        }
        else if ($sKey)
        {
            return false;
        }
        
        return $this->_aUserData;
    }

	/**
     * @see X_User_Interface
     */
    public function getPrintableName()
    {
        // @todo format printable name
       	$this->_aUserData['printable_name'];
    }

	/**
     * @see X_User_Interface
     */
    public function getName()
    {
        return $this->_aUserData['name'];
    }
	/**
     * @see X_User_Interface
     */
    public function setPrintableName($sPrintableName)
    {
        $this->_aUserData['printable_name'] = (string)$sPrintableName;
    }

	/**
     * @see X_User_Interface
     */
    public function setName($sName)
    {
        $this->_aUserData['name'] = (string)$sName;
    }

    
    /**
     * this method knows how to login the user (identify/authenticate)
     * ex. forward to a login page
     * 
     * @see X_User_Interface
     * @return X_User
     */
    public function identify()
    {
        // if it is already logged in we have already identified
        if ($this->confirm()) return true;
        // make sure we have some sort of athority
        if ($this->_checkIdAuthority())
        {
            if($this->_oId->verifyUserSession($this))
            {
                return '';
            }
            else
            {
                return $this->_oId->identify();                
            }
        
        }
        
        return false;
    }
    
    /**
     * @see X_User_Interface
     * @return string
     */
    public function getUid()
    {
        return $this->_sUid;
    }
    
	/**
     * @param unknown $xId
     * @return X_User
     */
    public function setUid($xId)
    {
        $this->_sUid = $xId;
        return $this;
    }
    /**
     * @see X/User/X_User_Interface#setEmail($sEmailAddress)
     */
    public function setEmail($sEmailAddress)
    {
    	$this->_aUserData['email'] = (string)$sEmailAddress;
    }
    /**
     * @see X/User/X_User_Interface#getEmail()
     * @return string
     */
    public function getEmail()
    {
        return $this->_aUserData['email'];
    }
    
    /**
     * @see X_User_Interface
     * 
     * @param string $sSubjectUri
     * @param string $sDetail
     */
    public function isPermitted($sSubjectUri, $sDetail)
    {
        if (!$this->_checkPermissionAuthority()) return false;
        return $this->_oPermission->isPermitted($this, $sSubjectUri, $sDetail);
    }
    
    /**
     * user data wrapper
     * @param $sName
     */
    function __get($sName)
    {
    	//translate name
    	switch ($sName) {
    		case 'sUsername':
    			$sName = 'name';
    			break;
    		case 'sPrintableName':
    			$sName = 'printable_name';
    			break;
    		case 'sEmail':
    			$sName = 'email';
    			break;
    		break;
    	}
    	
    	if (array_key_exists($sName, $this->_aUserData))
    	{
    		return $this->_aUserData[$sName];
    	}
    	
    	return false;
    }
}